// 谷歌密钥生成操作
package xgoogauth

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base32"
	"time"
)

type Config struct {
	LogErrorFunc func(msg string, err error) // 日志导出函数
}

var _default Config = Config{
	LogErrorFunc: func(msg string, err error) {},
}

// 注册配置项
func Regedit(c *Config) {
	if c == nil {
		return
	}
	if c.LogErrorFunc != nil {
		_default.LogErrorFunc = c.LogErrorFunc
	}
}

func un() int64 {
	return time.Now().UnixNano() / 1000 / 30
}

func hmacSha1(key, data []byte) []byte {
	h := hmac.New(sha1.New, key)
	if total := len(data); total > 0 {
		h.Write(data)
	}
	return h.Sum(nil)
}

func base32encode(src []byte) string {
	return base32.StdEncoding.EncodeToString(src)
}

func base32decode(s string) ([]byte, error) {
	return base32.StdEncoding.DecodeString(s)
}

func toBytes(value int64) []byte {
	var result []byte
	mask := int64(0xFF)
	shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
	for _, shift := range shifts {
		result = append(result, byte((value>>shift)&mask))
	}
	return result
}

func toUint32(bts []byte) uint32 {
	return (uint32(bts[0]) << 24) + (uint32(bts[1]) << 16) +
		(uint32(bts[2]) << 8) + uint32(bts[3])
}

func oneTimePassword(key []byte, data []byte) uint32 {
	hash := hmacSha1(key, data)
	offset := hash[len(hash)-1] & 0x0F
	hashParts := hash[offset : offset+4]
	hashParts[0] = hashParts[0] & 0x7F
	number := toUint32(hashParts)
	return number % 1000000
}
